<?php

namespace app\queue\stomp;

use app\queue\BaseConsumer;
use common\model\EntityModel;
use common\model\NoteEntityRelationModel;
use common\model\StatusModel;

class NoteRelationAfterUpdateEntityStatus extends BaseConsumer
{

    // 要消费的队列名
    public $queue = 'note_relation_after_update_entity_status';

    // 连接名，对应 config/redis_queue.php 里的连接`
    public $connection = 'default';

    /**
     * @param $data
     * @return void
     */
    public function doConsume($data)
    {
        $changeType = $data['type'];

        $changedRelations = array_values($data['changed']);
        if (empty($changedRelations[0]['project_id'])) {
            return;
        }
        $projectId = $changedRelations[0]['project_id'];
        $demandStatus = model(StatusModel::class)->where(['code' => ['IN', ['wait_demand', 'already_relate']]])->select();
        $demandStatus = array_column($demandStatus, 'id', 'code');
        try {
            switch ($changeType) {
                case 'add':
                    $changedGroupRelations = array_group_by($changedRelations, 'relation_type');
                    $updateEntityIds = [];
                    foreach ($changedGroupRelations as $key => $value) {
                        switch ($key) {
                            case 'entity':
                            case 'step':
                                $updateEntityIds = array_unique(array_column($value, 'entity_id'));
                                break;
                            case 'episode':
                                $episodeMap = array_column($value, 'episode_code');
                                $page = 1;
                                while (true) {
                                    $entityList = model(EntityModel::class)
                                        ->field("entity.id as id, json_extract(json, concat('$.',m.code, '_demand_status')) as demand_status")
                                        ->join('module m on m.id = entity.module_id')
                                        ->where(['entity.initial_episode_code' => ['IN', $episodeMap], 'entity.project_id' => $projectId, 'm.code' => 'storyboard'])
                                        ->page($page, 100)
                                        ->select();
                                    if (empty($entityList)) {
                                        break;
                                    }
                                    foreach ($entityList as $item) {
                                        if (empty($item['demand_status']) || $item['demand_status'] == $demandStatus['wait_demand']) {
                                            $updateEntityIds[] = $item['id'];
                                        }
                                    }
                                    $page++;
                                }
                                break;
                        }
                    }
                    if ($updateEntityIds) {
                        $updateEntityIds = implode(',', $updateEntityIds);
                        model(EntityModel::class)->execute("UPDATE entity join module m on m.id = entity.module_id SET entity.json = JSON_SET(IFNULL(entity.json, '{}'), concat('$.',m.code, '_demand_status'), {$demandStatus['already_relate']}) where entity.id in ($updateEntityIds)");
                    }
                    break;
                case 'deleted':
                    $changedGroupRelations = array_group_by($changedRelations, 'relation_type');
                    $updateEntityIds = [];
                    $shotEntityList = [];
                    $episodeEntityCodes = [];
                    foreach ($changedGroupRelations as $key => $value) {
                        switch ($key) {
                            case 'entity':
                            case 'step':
                                $noteRelateEntityIds = array_unique(array_column($value, 'entity_id'));
                                $noteRelateList = model(NoteEntityRelationModel::class)->where(['entity_id' => ['IN', $noteRelateEntityIds], 'relation_type' => ['IN', 'entity,step']])->select();
                                $noteRelatesMap = array_column($noteRelateList, 'entity_id');
                                // 先比对实体ID找到已经没有关联需求的实体预留更新，如果有镜头module_code的则保留二次查询所属剧集是否有关联需求
                                foreach ($value as $item) {
                                    if (!in_array($item['entity_id'], $noteRelatesMap)) {
                                        $updateEntityIds[] = $item['entity_id'];
                                        if ($item['relate_module_code'] == 'shot') {
                                            $shotEntityList[] = $item;
                                        }
                                    }
                                }
                                break;
                            case 'episode':
                                $noteRelateEpisodes = array_column($value, 'episode_code');
                                $noteRelateList = model(NoteEntityRelationModel::class)->where(['episode_code' => ['IN', $noteRelateEpisodes], 'project_id' => $projectId, 'relation_type' => $key])->select();
                                $noteRelatesMap = array_column($noteRelateList, 'episode_code');
                                // 先预留已经没有关联需求的剧集，然后再去查找该剧集下所有不在关联需求表中的镜头进行更新状态
                                foreach ($value as $item) {
                                    if (!in_array($item['episode_code'], $noteRelatesMap)) {
                                        $episodeEntityCodes[] = $item['episode_code'];
                                    }
                                }
                                break;
                        }
                    }
                    if ($episodeEntityCodes) {
                        $page = 1;
                        while (true) {
                            $entityIds = model(EntityModel::class)
                                ->field('entity.id as id')
                                ->join('module m on m.id = entity.module_id')
                                ->where(['entity.initial_episode_code' => ['IN', $episodeEntityCodes], 'entity.project_id' => $projectId, 'm.code' => 'storyboard'])
                                ->page($page, 100)
                                ->column('id');
                            if (empty($entityIds)) {
                                break;
                            }
                            // 找到没有单独需求的实体镜头
                            $noteRelateShotEntityIds = model(NoteEntityRelationModel::class)
                                ->where(['entity_id' => ['IN', $entityIds], 'relation_type' => ['IN', 'entity,step']])
                                ->group('entity_id')
                                ->column('entity_id');
                            foreach ($entityIds as $item) {
                                if (!in_array($item, $noteRelateShotEntityIds)) {
                                    $updateEntityIds[] = $item;
                                }
                            }
                            $page++;
                        }
                    }
                    if ($shotEntityList) {
                        $noteRelateFilterEpisode = array_column($shotEntityList, 'episode_code');
                        $noteRelateEpisodeList = model(NoteEntityRelationModel::class)->where(['episode_code' => ['IN', $noteRelateFilterEpisode], 'project_id' => $projectId])->column('episode_code');
                        foreach ($shotEntityList as $item) {
                            // 如果该集有需求，则属于该集的镜头不允许删除需求状态
                            if (in_array($item['episode_code'], $noteRelateEpisodeList)) {
                                foreach ($updateEntityIds as $key => $value) {
                                    if ($value == $item['entity_id']) {
                                        unset($updateEntityIds[$key]);
                                    }
                                }
                            }
                        }
                    }
                    if ($updateEntityIds) {
                        $updateEntityIds = implode(',', $updateEntityIds);
                        model(EntityModel::class)->execute("UPDATE entity join module m on m.id = entity.module_id SET entity.json = JSON_SET(IFNULL(entity.json, '{}'), concat('$.',m.code, '_demand_status'), {$demandStatus['wait_demand']}) where entity.id in ($updateEntityIds)");
                    }
                    break;
            }
        } catch (\Throwable $e) {
            trace(format_exception_info($e), 'ERR');
        }
    }
}